package com.splic.product.service.impl;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryResult;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
import com.github.pagehelper.Page;
import com.splic.common.core.DeviceContext;
import com.splic.common.enums.GoodsCycleEnum;
import com.splic.common.enums.OrderStatusEnum;
import com.splic.common.exception.BusinessException;
import com.splic.common.utils.DateUtils;
import com.splic.common.utils.RandomCodeUtil;
import com.splic.common.utils.SpringBeansUtil;
import com.splic.common.utils.StringUtils;
import com.splic.product.domain.*;
import com.splic.product.dto.CreateOrderDto;
import com.splic.product.dto.CreateOrderReturnDto;
import com.splic.product.dto.OrderDto;
import com.splic.product.mapper.OrderMapper;
import com.splic.product.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 订单Service业务层处理
 * 
 * @author singe
 * @date 2022-01-04
 */
@Service
@Slf4j
public class OrderServiceImpl implements OrderService
{
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private GoodsServiceImpl goodsServiceImpl;
    @Autowired
    private GoodsTypeService goodsTypeServiceImpl;
    @Autowired
    private UserSubRecordService userSubRecordServiceImpl;
    @Autowired
    private ProductService productServiceImpl;
    @Autowired
    private UserService userServiceImpl;
    @Autowired
    private DeviceService deviceServiceImpl;

    /**
     * 查询订单
     * 
     * @param id 订单主键
     * @return 订单
     */
    @Override
    public Order selectOrderById(Long id)
    {
        return orderMapper.selectOrderById(id);
    }

    /**
     * 查询订单列表
     * 
     * @param orderDto 订单
     * @return 订单
     */
    @Override
    public List<OrderDto> selectPageList(OrderDto orderDto)
    {

        Page<OrderDto> orderDtoPage = new Page<>();
//        Order order = new Order();
//        BeanUtils.copyProperties(orderDto,order);

        if (StringUtils.isNotEmpty(orderDto.getUserIdentify())){
            User user = userServiceImpl.getByUserIdentify(orderDto.getUserIdentify());
            if(user != null){
                orderDto.setUserId(user.getId());
            }
        }
        if (StringUtils.isNotEmpty(orderDto.getDeviceIdentify())){
            Device device = deviceServiceImpl.getByDeviceIdentify(orderDto.getDeviceIdentify());
            if(device != null){
                orderDto.setDeviceId(device.getId());
            }
        }
        if (StringUtils.isEmpty(orderDto.getStartCreateTime())) {
            orderDto.setStartCreateTime(DateUtil.formatDate(DateUtil.offsetDay(new Date(), -1)));
        }
        if (StringUtils.isEmpty(orderDto.getEndCreateTime())) {
            orderDto.setEndCreateTime(DateUtil.formatDate(DateUtil.offsetDay(new Date(), 1)));
        } else {
            orderDto.setEndCreateTime(DateUtil.formatDate(DateUtil.offsetDay(DateUtils.parseDate(orderDto.getEndCreateTime()), 1)));
        }
        Page<Order> orderPage = orderMapper.selectOrderList(orderDto);
        if(CollectionUtils.isNotEmpty(orderPage)) {
            Set<Long> userIdSet = orderPage.stream().map(Order::getUserId).collect(Collectors.toSet());
            Map<Long, String> userMap = null;
            if (CollectionUtils.isNotEmpty(userIdSet)) {
                List<User> userList = userServiceImpl.getByIds(userIdSet);
                if (CollectionUtils.isNotEmpty(userList)) {
                    userMap = userList.stream().collect(Collectors.toMap(User::getId, User::getUserIdentify));
                }
            }

            Set<Long> deviceIdSet = orderPage.stream().filter(o -> o.getDeviceId() != null).map(Order::getDeviceId).collect(Collectors.toSet());
            Map<Long, String> deviceMap = null;
            if (CollectionUtils.isNotEmpty(deviceIdSet)) {
                List<Device> deviceList = deviceServiceImpl.getByIds(deviceIdSet);
                if (CollectionUtils.isNotEmpty(deviceList)) {
                    deviceMap = deviceList.stream().collect(Collectors.toMap(Device::getId, Device::getDeviceIdentify));
                }
            }
            OrderDto dto = null;
            for(Order g :orderPage){
                dto = new OrderDto();
                BeanUtils.copyProperties(g,dto);

                if(userMap!= null){
                    dto.setUserIdentify(userMap.get(g.getUserId()));
                }
                if(deviceMap!= null){
                    dto.setDeviceIdentify(deviceMap.get(g.getDeviceId()));
                }
                orderDtoPage.add(dto);
            }
        }
        orderDtoPage.setTotal(orderPage.getTotal());
        return orderDtoPage;
    }

    /**
     * 查询订单列表
     *
     * @param order 订单
     * @return 订单
     */
    @Override
    public List<Order> selectOrderList(OrderDto order)
    {
        return orderMapper.selectOrderList(order);
    }

    /**
     * 新增订单
     * 
     * @param order 订单
     * @return 结果
     */
    @Override
    public int insert(Order order)
    {
        order.setCreateTime(DateUtils.getNowDate());
        return orderMapper.insert(order);
    }

    /**
     * 修改订单
     * 
     * @param order 订单
     * @return 结果
     */
    @Override
    public int update(Order order)
    {
        order.setUpdateTime(DateUtils.getNowDate());
        return orderMapper.update(order);
    }

    @Override
    public Order getByOrderNo(String orderNo) {
        return orderMapper.selectOrderByOrderNo(orderNo);
    }

    /**
     * 删除订单信息
     * 
     * @param id 订单主键
     * @return 结果
     */
    @Override
    public int deleteById(Long id)
    {
        return orderMapper.deleteById(id);
    }
    /**
     * 修改订单
     *
     * @param order 订单信息
     * @return 结果
     */
    @Override
    @Transactional
    public int saveOrUpdate(Order order)
    {
        if(order.getId() != null){
            order.setUpdateTime(new Date());
            return orderMapper.update(order);
        }else{
            order.setCreateTime(new Date());
            return orderMapper.insert(order);
        }
    }

    /**
     * 创建订单
     *
     * @return 结果
     */
    @Override
    public CreateOrderReturnDto createOrder(CreateOrderDto createOrderDto)
    {
        Goods goods = goodsServiceImpl.selectGoodsById(createOrderDto.getGoodsId());
        if(goods == null){
            throw new BusinessException("服务套餐查询失败。");
        }
        Order order = new Order();
        order.setPayType(createOrderDto.getPayType());
        order.setGoodsId(createOrderDto.getGoodsId());
        order.setUserId(createOrderDto.getUserId());
        order.setAmount(goods.getSalePrice());
        order.setOrderNo(RandomCodeUtil.havePrefixOrderNo("OR"));
        order.setStatus(OrderStatusEnum.UN_PAY.getCode());
        order.setCreateTime(DateUtils.getNowDate());
        GoodsType goodsType = goodsTypeServiceImpl.selectGoodsTypeById(goods.getGoodsTypeId());
        if(goodsType == null){
            throw new BusinessException("服务查询失败。");
        }
        order.setGoodsTypeId(goodsType.getId());
        order.setGoodsTypeName(goodsType.getName());
        Product product = productServiceImpl.selectProductById(goodsType.getProductId());
        if(product == null){
            throw new BusinessException("应用查询失败");
        }
        order.setGoodsName(product.getName() + "-" +goods.getName());
        order.setProductId(product.getId());
        order.setProductName(product.getName());
        order.setProductVersion(DeviceContext.getVersion());
        order.setDeviceId(DeviceContext.getDeviceId());
        int count = orderMapper.insert(order);
        if(count <= 0){
            throw new BusinessException("下单失败");
        }

        //查询支付接口是否存在
        ThirdPayService thirdpayService = SpringBeansUtil.getBean(createOrderDto.getPayType() + "PayService", ThirdPayService.class);
        CreateOrderReturnDto returnDto = thirdpayService.createPayOrder(order,createOrderDto);
        if (returnDto == null) {
            throw new BusinessException("创建支付订单失败");
        }

        updateThirdOrderNo(order.getOrderNo(),returnDto.getPrepayId());

        returnDto.setOrderNo(order.getOrderNo());
        return returnDto;
    }

    private void updateThirdOrderNo(String orderNo, String payNo) {
        if(StringUtils.isNotEmpty(payNo)){
            orderMapper.updateThirdOrderNo(payNo,orderNo);
        }
    }

    /**
     * 校验订单是否支付成功
     * @param orderNo
     * @return
     */
    @Override
    public Boolean checkOrder(String orderNo) {
        Order order = orderMapper.selectOrderByOrderNo(orderNo);
        if(order == null){
            throw new BusinessException("订单查询失败");
        }
        if(Objects.equals(OrderStatusEnum.PAY_SUCCESS.getCode(),order.getStatus())){
            return true;
        }
        ThirdPayService thirdpayService = SpringBeansUtil.getBean(order.getPayType() + "PayService", ThirdPayService.class);
        int status = thirdpayService.checkOrder(order);
        if (status == -1) {
            throw new BusinessException("订单查询失败");
        }
        if(Objects.equals(OrderStatusEnum.PAY_SUCCESS.getCode(),order.getStatus())){
            return true;
        }
        return false;
    }

    /**
     * 更新订单状态
     * @param order
     * @return
     */
    @Override
    @Transactional
    @Async
    public void updateOrderStatus(Order order) {
        Order orderNew = orderMapper.selectOrderById(order.getId());
        if(orderNew == null){
            log.error("订单状态更新失败,订单不存在,订单号:{}",order.getOrderNo());
            return ;
        }
        if(OrderStatusEnum.PAY_SUCCESS.getCode() == orderNew.getStatus()){
            return ;
        }
        orderNew.setStatus(OrderStatusEnum.PAY_SUCCESS.getCode());
        int count = orderMapper.update(orderNew);
        if(count <= 0){
            log.error("订单状态更新失败,订单号:{}",order.getOrderNo());
            return ;
        }
        Goods goods = goodsServiceImpl.selectGoodsById(orderNew.getGoodsId());
        if(goods == null){
            log.error("订单状态更新失败,订单商品查询失败,订单号:{}",order.getOrderNo());
            return ;
        }
        GoodsType goodsType = goodsTypeServiceImpl.selectGoodsTypeById(orderNew.getGoodsTypeId());
        if (goodsType.getServiceNature() != null && "time".equals(goodsType.getServiceNature())) {
            UserSubRecord userSubRecordDto = new UserSubRecord();
            userSubRecordDto.setUserId(orderNew.getUserId());
            userSubRecordDto.setProductId(orderNew.getProductId());
            userSubRecordDto.setGoodsTypeId(goods.getGoodsTypeId());
            userSubRecordDto.setProductName(orderNew.getProductName());
            userSubRecordServiceImpl.updateUserSubInfoTime(userSubRecordDto, new BigDecimal(goods.getCycle()),orderNew, goods);
        } else {
            Integer dayNum = GoodsCycleEnum.getByCode(goods.getCycle());
            if(dayNum == null){
                log.error("订单状态更新失败,订单商品对应周期天数获取失败,订单号:{}",order.getOrderNo());
                return ;
            }

            UserSubRecord userSubRecordDto = new UserSubRecord();
            userSubRecordDto.setUserId(orderNew.getUserId());
            userSubRecordDto.setProductId(orderNew.getProductId());
            userSubRecordDto.setGoodsTypeId(goods.getGoodsTypeId());
            userSubRecordDto.setProductName(orderNew.getProductName());
            userSubRecordServiceImpl.updateUserSubInfo(userSubRecordDto,dayNum,orderNew, goods);
        }

    }

}
